package xyz.ylx.proxy.select;


import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.DefaultPointcutAdvisor;

public class Main {

    public static void main(String[] args) {
        /*
            两个切面的概念
            aspect =
                通知1(advice) + 切点1(pointcut)
                通知2(advice) + 切点2(pointcut)
                通知3(advice) + 切点3(pointcut)
                ...
            advisor = 粒度更细的切面，包含一个通知和切点
         */

        // 1. 备好切点
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(* foo())");

        // 2. 备好通知
        MethodInterceptor advice = invocation -> {
            System.out.println("before");
            Object result = invocation.proceed();
            System.out.println("after");
            return result;
        };

        // 3. 备好切面
        DefaultPointcutAdvisor advisor = new DefaultPointcutAdvisor(pointcut, advice);

        /*
            4. 创建代理
                a. proxyTargetClass = false，目标实现了接口，用 jdk 实现
                b. proxyTargetClass = false, 目标没有实现皆苦，用 cglib 实现
                c. proxyTargetClass = true, 用cglib实现
         */
        Target1 target1 = new Target1();
        ProxyFactory factory = new ProxyFactory();
        factory.setTarget(target1);
        factory.addAdvisor(advisor);
        factory.setInterfaces(target1.getClass().getInterfaces());
        factory.setProxyTargetClass(true);
        I1 proxy = (I1) factory.getProxy();
        System.out.println(proxy.getClass());
        proxy.foo();
        proxy.bar();

        Target2 target2 = new Target2();
        ProxyFactory factory2 = new ProxyFactory();
        factory2.setTarget(target2);
        factory2.addAdvisor(advisor);
        factory2.setInterfaces(target2.getClass().getInterfaces());
        Target2 proxy2 = (Target2) factory2.getProxy();
        System.out.println(proxy2.getClass());
        proxy2.foo();
        proxy2.bar();
    }
}
